#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_errno.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "iot_i2c.h"
#include "kp_base_type.h"
#include "iot_fan_SHT30.h"

#define SHT30_SDA_NAME_GPIO_13  13
#define SHT30_SCL_NAME_GPIO_14  14
#define SHT30_IIC_IDX_0  0
#define SHT30_IIC_BAUDRATE  400000


/* IIC功能初始化 */
void ShtIICInit(void)
{
    // 初始化SHT30 SDA引脚
    u32 ret = IoTGpioInit(SHT30_SDA_NAME_GPIO_13);
	if(ret != 0){ 
        printf("IoTGpioInit failed :%#x \r\n",ret);
		return;
    }

	/* 设置复用为IIC功能 */
	ret = IoTGpioSetFunc(SHT30_SDA_NAME_GPIO_13, IOT_GPIO_FUNC_GPIO_13_I2C0_SDA);
	if(ret != 0){ 
        printf("IoTGpioSetFunc failed :%#x \r\n",ret);
		return;
    }
	
	// 初始化SHT30 SCL引脚
    ret = IoTGpioInit(SHT30_SCL_NAME_GPIO_14);
	if(ret != 0){ 
        printf("IoTGpioInit failed :%#x \r\n",ret);
		return;
    }

	/* 设置复用为IIC功能 */
	ret = IoTGpioSetFunc(SHT30_SCL_NAME_GPIO_14, IOT_GPIO_FUNC_GPIO_14_I2C0_SCL);
	if(ret != 0){ 
        printf("IoTGpioSetFunc failed :%#x \r\n",ret);
		return;
    }

    /* IIC初始化 */
	ret = IoTI2cInit(SHT30_IIC_IDX_0, SHT30_IIC_BAUDRATE);
    if (ret != 0) {
        printf("IoTI2cInit failed :%#x \r\n",ret); 
        return;
    }

    /* IIC设置波特率 */
	ret = IoTI2cSetBaudrate(SHT30_IIC_IDX_0, SHT30_IIC_BAUDRATE);
    if (ret != 0) {
        printf("IoTI2cSetBaudrate failed :%#x \r\n",ret); 
        return;
    }
	
    printf("----- ShtIICInit success! -----\r\n");
}

static unsigned char SHT3X_CalcCrc(unsigned char data[], unsigned int nbrOfBytes) 
{
    unsigned char bit; // bit mask
    unsigned char crc = 0xFF; // calculated checksum
    unsigned char byteCtr; // byte counter

    // calculates 8-Bit checksum with given polynomial
    for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
    {
        crc ^= (data[byteCtr]);
        for(bit = 8; bit > 0; --bit)
        {
            if(crc & 0x80) 
                crc = (crc << 1) ^ POLYNOMIAL;
            else 
                crc = (crc << 1);
        }
    }

    return crc; 
}

static etError SHT3X_CheckCrc(unsigned char data[],\
    unsigned int nbrOfBytes, unsigned char checksum) 
{
    unsigned char crc; // calculated checksum

    // calculates 8-Bit checksum
    crc = SHT3X_CalcCrc(data, nbrOfBytes);

    // verify checksum
    if(crc != checksum) 
        return CHECKSUM_ERROR;
    else 
        return NO_ERROR; 
}

static int SHT3x_ReadSerialNumber(unsigned int *serialNumber)
{
    unsigned int ret = 0;
    unsigned char serialNumWords[6] = {0};
    unsigned char cmd[2] = {0x37,0x80,};
    
	ret = IoTI2cWrite(SHT30_IIC_IDX_0, ((unsigned char)0x44) << 1, cmd, sizeof(cmd));
    if(ret != 0){
        printf("SHT3x_ReadSerialNumber IoTI2cWrite failed ret :%#x \r\n",ret);
        return ret;
    }
    
	ret = IoTI2cRead(SHT30_IIC_IDX_0, ((unsigned char)0x44) << 1 | 0x01, serialNumWords, sizeof(serialNumWords));
    if(ret != 0){
        printf("SHT3x_ReadSerialNumber IoTI2cRead failed ret :%#x \r\n",ret);
        return ret;
    }
    //dump_buf(serialNumWords,sizeof(serialNumWords));
    
    ret = SHT3X_CheckCrc(serialNumWords,2,serialNumWords[2]);
    if(ret != NO_ERROR){
        printf("read serial number crc check failed \r\n"); 
        return ret;
    }
    
    ret = SHT3X_CheckCrc(&serialNumWords[3],2,serialNumWords[5]);
    if(ret != NO_ERROR){
        printf("read serial number crc check failed \r\n"); 
        return ret;
    }
    return ret;
}

static int SHT3x_WriteCMD(unsigned short cmd)
{
    unsigned int  ret = 0;
    unsigned char sendbuf[2] = {0};
    unsigned char rcvbuf[2] = {0};
    
    sendbuf[0] = (cmd & 0xff00) >> 8;
    sendbuf[1] = cmd & 0xff;
    //dump_buf(sendbuf,2); 
	ret = IoTI2cWrite(SHT30_IIC_IDX_0, ((unsigned char)0x44) << 1, sendbuf, sizeof(sendbuf));
    if(ret != 0){
        printf("SHT3x_WriteCMD IoTI2cWrite failed, cmd : %#x, ret :%#x \r\n", cmd, ret);
        return ret;
    }
    return 0;        
}

static int SHT3x_Read4BytesDataAndCrc(unsigned short *data)
{
    unsigned int  ret = 0;
    unsigned char sendbuf[2] = {0};
    unsigned char rcvbuf[6] = {0};
    
    if(data == NULL){
        printf("SHT3x_Read4BytesDataAndCrc invalid para \r\n");
        return ret;
    }
    
	ret = IoTI2cRead(SHT30_IIC_IDX_0, ((unsigned char)0x44) << 1 | 0x01, rcvbuf, sizeof(rcvbuf));
    if(ret != 0){
        printf("SHT3x_Read4BytesDataAndCrc IoTI2cRead failed ret :%#x \r\n",ret);
        return ret;
    }
    
    ret = SHT3X_CheckCrc(rcvbuf,2,rcvbuf[2]);
    if(ret != NO_ERROR){
        printf("read serial number crc check failed \r\n"); 
        return ret;
    }
    
    ret = SHT3X_CheckCrc(&rcvbuf[3],2,rcvbuf[5]);
    if(ret != NO_ERROR){
        printf("read serial number crc check failed \r\n"); 
        return ret;
    }
    
    data[0] = rcvbuf[0] << 8 | rcvbuf[1];
    data[1] = rcvbuf[3] << 8 | rcvbuf[4];
    
    return 0;        
}

static int SHT3x_Read2BytesDataAndCrc(unsigned short *data)
{
    unsigned int  ret = -1;
    unsigned char sendbuf[2] = {0};
    unsigned char rcvbuf[3] = {0};
        
    if(data == NULL){
        printf("SHT3x_Read2BytesDataAndCrc invalid para \r\n");
        return ret;
    }
    
    ret = IoTI2cRead(SHT30_IIC_IDX_0, ((unsigned char)0x44) << 1 | 0x01, rcvbuf, sizeof(rcvbuf));
    if(ret != 0){
        printf("SHT3x_Read2BytesDataAndCrc IoTI2cRead failed ret :%#x \r\n",ret);
        return ret;
    }
    
    ret = SHT3X_CheckCrc(rcvbuf,2,rcvbuf[2]);
    if(ret != NO_ERROR){
        printf("read serial number crc check failed \r\n"); 
        return ret;
    }

    data[0] = rcvbuf[0] << 8 | rcvbuf[1];
    return 0;        
}

void SHT3X_SoftReset_t(void)
{
    SHT3x_WriteCMD(CMD_SOFT_RESET);
}

void SHT3X_ReadSerialNumber_t(void) 
{
    unsigned short data[2] = {0};
    SHT3X_SoftReset_t();
    SHT3x_WriteCMD(CMD_READ_SERIALNBR);

    SHT3x_Read4BytesDataAndCrc(data);
    printf("--------------------------------\r\n");
    //dump_buf((unsigned char *)data,sizeof(data));
}

static void SHT3X_ReadStatus(unsigned short* status) 
{
    SHT3x_WriteCMD(CMD_READ_STATUS);
    SHT3x_Read2BytesDataAndCrc(status);
}

static void SHT3X_ClearAllAlertFlags(void)
{
    SHT3x_WriteCMD(CMD_CLEAR_STATUS);
}

/*
static void SHT3X_StartPeriodicMeasurment(void)
{
    // medium repeatability, 2.0 Hz
    SHT3x_WriteCMD(CMD_MEAS_PERI_2_M);
}
*/
static float SHT3X_CalcTemperature_t(unsigned short rawValue) 
{
    return 175.0f * (float)rawValue / 65535.0f - 45.0f; 
}

static float SHT3X_CalcHumidity_t(unsigned short rawValue) 
{
    return 100.0f * (float)rawValue / 65535.0f; 
}

/* SHT3X模块IIC功能初始化 */
void SHT3X_init(void)
{
    int ret = 0;
    unsigned short data[2] = {0};
    //SHT3X_SoftReset_t();
    SHT3x_WriteCMD(CMD_READ_SERIALNBR);
    osDelay(100);
    SHT3x_WriteCMD(CMD_MEAS_PERI_2_M);
    //SHT3X_StartPeriodicMeasurment();
}

/* 利用IIC从SHT30设备读取温度和湿度数据 */
void SHT3X_ReadMeasurementBuffer(float* temperature, float* humidity) 
{

    unsigned int rawValueTemp = 0; 
    
    SHT3x_WriteCMD(CMD_FETCH_DATA);
    SHT3x_Read4BytesDataAndCrc((unsigned short *)&rawValueTemp);

    //dump_buf((unsigned char *)&rawValueTemp,sizeof(rawValueTemp));    

    *temperature = SHT3X_CalcTemperature_t(rawValueTemp);
    *humidity = SHT3X_CalcHumidity_t(*((unsigned short *)(&rawValueTemp)+1));
}

static void SHT3X_ReadMeasurementVal(unsigned int para)
{
    (void) para;
    static int cunt = 0;
    static float humidity = 0.0; 
    static float temperature = 0.0; 
    
    SHT3X_ReadMeasurementBuffer(&temperature, &humidity);
 
}

void *MonitorShtTask(void * para) /* 温湿度传感器处理函数 */
{
    while(1){
        sleep(2);
        SHT3X_ReadMeasurementVal(0);
        printf("sth task \r\n");
    }
    return NULL;
}


